﻿using Abp.Application.Features;
using Abp.Authorization;
using Abp.Extensions;
using Abp.UI;
using Microsoft.AspNetCore.Http;
using Mt.Site.Core.Authorization;
using Mt.Site.Core.Base.Utils.Excel;
using Mt.Site.Core.Base.Utils.Excel.Import;
using Mt.Site.Core.Features;
using Mt.Site.Core.Web;
using Mt.Site.Core.Web.Rewriters;
using NPOI.SS.UserModel;
using System;
using System.Collections.Generic;
using System.IO;

namespace Mt.Site.Application.Web
{
    public class RewriteAppService : MtSiteAppServiceBase, IRewriteAppService
    {
        private readonly ITenancyNameFinder _tenancyNameFinder;
        private readonly IRewriteUrlsByMap _rewriteUrlsByMap;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public RewriteAppService(ITenancyNameFinder tenancyNameFinder, IRewriteUrlsByMap rewriteUrlsByMap, IHttpContextAccessor httpContextAccessor)
        {
            _tenancyNameFinder = tenancyNameFinder;
            _rewriteUrlsByMap = rewriteUrlsByMap;
            _httpContextAccessor = httpContextAccessor;
        }

        [RequiresFeature(AppFeatures.UrlRewriteByMap)]
        [AbpAuthorize(AppPermissions.Pages_UrlRewriteByMap)]
        public string ImportUrlMapsData()
        {
            var helper = new OldUrlsImportHelper(this._tenancyNameFinder,this._rewriteUrlsByMap);
            try
            {
                var result = new ExcelImport<DataType>(helper).Inport(_httpContextAccessor.HttpContext.Request, "file", 20, 1);

                SaveFile(helper.Data);

                _rewriteUrlsByMap.LoadData();

                return $"{ L("expotAllNum")}:{result.Num},{L("exportSuccessNum")}:{helper.Data.Count},{L("DuplicateItems")}({helper.Rejects.Count}):\n{string.Join(",\n", helper.Rejects)}"  ;
            }
            catch(Exception ex)
            {
                throw new UserFriendlyException("Upload error :"+ ex.Message);
            }
        }

        private void SaveFile(Dictionary<string, string> data)
        {
            var dirPath = _rewriteUrlsByMap.DirPath;
            if (!Directory.Exists(dirPath))
                Directory.CreateDirectory(dirPath);

            var path = Path.Combine(dirPath, $"{AbpSession.TenantId}.txt");
            using (FileStream fs = new FileStream(path, FileMode.Create))
            using (StreamWriter sw = new StreamWriter(fs))
            {
                foreach (var item in data)
                {
                    sw.WriteLine($"{item.Key},{item.Value}");
                    sw.Flush();
                }
            }
        }

        private class DataType
        {
            public string FromUrl { get; set; }

            public string ToUrl { get; set; }

            public bool IsOk { get; set; }
        }

        private class OldUrlsImportHelper : ExcelImport<DataType>.ExcelImportHelper
        {
            private readonly ITenancyNameFinder _tenancyNameFinder;
            private readonly IRewriteUrlsByMap _rewriteUrlsByMap;
            public Dictionary<string, string> Data = new Dictionary<string, string>();
            public List<string> Rejects = new List<string>();

            public OldUrlsImportHelper(ITenancyNameFinder tenancyNameFinder, IRewriteUrlsByMap rewriteUrlsByMap)
            {
                _tenancyNameFinder = tenancyNameFinder;
                _rewriteUrlsByMap = rewriteUrlsByMap;
            }

            public void Add(DataType model)
            {
                if (model.IsOk)
                {
                    if (Data.ContainsKey(model.FromUrl))
                    {
                        if (!Rejects.Contains(model.FromUrl))
                        {
                            Rejects.Add(model.FromUrl);
                        }
                    }
                    Data[model.FromUrl] = model.ToUrl;
                }
                else if(!model.FromUrl.IsNullOrEmpty())
                {
                    if (!Rejects.Contains(model.FromUrl))
                    {
                        Rejects.Add(model.FromUrl);
                    }
                }
            }

            public DataType IsExist(IRow row)
            {
                return null;
            }

            public bool Map(IRow row, DataType model)
            {
                string fromUrlStr, toUrlStr;
                try
                {
                    fromUrlStr = row.GetValue<string>(0);
                    toUrlStr = row.GetValue<string>(1);
                }
                catch
                {
                    return false;
                }

                if (fromUrlStr.IsNullOrEmpty() || toUrlStr.IsNullOrEmpty())
                {
                    model.IsOk = false;
                    return true;
                }

                var fromUrl = new Uri(fromUrlStr);
                var toUrl = new Uri(toUrlStr);

                model.IsOk = true;
                model.FromUrl = fromUrl.PathAndQuery.ToLower();
                model.ToUrl = toUrl.AbsoluteUri;

                if (fromUrl.AbsolutePath == "/")
                {
                    model.IsOk = false;
                }

                //仅限跳转至站外链接或当前分站的链接
                if (!_rewriteUrlsByMap.CheckIfCanBeAccepted(toUrl, _tenancyNameFinder))
                {
                    model.IsOk = false;
                }

                return true;
            }

            public void Update(DataType model)
            {
                if (model.IsOk)
                    Data[model.FromUrl] = model.ToUrl;
            }
        }
    }
}
